﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using DevCorner.Weather.NotificationSVC;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.IO;
using System.Xml;
using System.Text;

namespace DevCorner.Weather
{
  public partial class MainPage : UserControl
  {
    NotificationSVC.NotificationServiceClient notificationClient;
    private ObservableCollection<CallbackArgs> trace = new ObservableCollection<CallbackArgs>();

    RegistrationSVC.RegistrationServiceClient registrationClient;

    public MainPage()
    {
      InitializeComponent();

      //Connect to Notification Service
      EndpointAddress address = new EndpointAddress("http://devcorner.info/Notifications/NotificationService.svc");
      PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll);

      notificationClient = new NotificationSVC.NotificationServiceClient(binding, address);
      notificationClient.NotifyOnMessageSendReceived += new EventHandler<NotificationSVC.NotifyOnMessageSendReceivedEventArgs>(client_NotifyOnMessageSendReceived);

      //Connect to Registration Service
      registrationClient = new RegistrationSVC.RegistrationServiceClient();
      registrationClient.GetRegisteredSubscribersCompleted += new EventHandler<RegistrationSVC.GetRegisteredSubscribersCompletedEventArgs>(registrationClient_GetRegisteredSubscribersCompleted);

      InitializeLocations();
      InitializeWeather();

      Log.ItemsSource = trace;
    }

    #region Initializations
    private void InitializeLocations()
    {
      List<string> locations = new List<string>();
      locations.Add("New York");
      locations.Add("London");
      locations.Add("Paris");
      locations.Add("Moscow");
      locations.Add("Jerusalem");

      cmbLocation.ItemsSource = locations;
      cmbLocation.SelectedIndex = 0;
    }

    private void InitializeWeather()
    {
      Dictionary<string, string> weather = new Dictionary<string, string>();
      weather.Add("Chance_Of_Showers", "Chance Of Showers");
      weather.Add("Clear", "Clear");
      weather.Add("Cloudy", "Cloudy");
      weather.Add("Cloudy_Period", "Cloudy Period");
      weather.Add("Cloudy_With_Dizzle", "Cloudy With Dazzle");
      weather.Add("Few_Flurries", "Few Flurries");
      weather.Add("Few_Flurries_Night", "Few Flurries Night");
      weather.Add("Few_Showers", "Few Showers");
      weather.Add("Flurries", "Flurries");
      weather.Add("Fog", "Fog");
      weather.Add("Freezing_Rain", "Freezing Rain");
      weather.Add("Mostly_Cloudy", "Mostly Cloudy");
      weather.Add("Mostly_Sunny", "Mostly Sunny");
      weather.Add("Rain", "Rain");
      weather.Add("Rain_Or_Snow", "Rain Or Snow");
      weather.Add("Risk_Of_Thundershowers", "Risk Of Thundershowers");
      weather.Add("Snow", "Snow");
      weather.Add("Sunny", "Sunny");
      weather.Add("Thunder_Showers", "Thunder Showers");
      weather.Add("Thunderstorms", "Thunderstorms");
      weather.Add("Wet_Flurries", "Wet Flurries");
      weather.Add("Wet Flurries Night", "Wet Flurries Night");

      cmbWeather.ItemsSource = weather;
      cmbWeather.DisplayMemberPath = "Value";
      cmbWeather.SelectedValuePath = "Key";
      cmbWeather.SelectedIndex = 0;
    }
    #endregion

    #region Event Handlers
    void client_NotifyOnMessageSendReceived(object sender, NotificationSVC.NotifyOnMessageSendReceivedEventArgs e)
    {
      if (null == e.Error)
        Dispatcher.BeginInvoke((Action)(() => { trace.Add(e.args); }));
      else
        Dispatcher.BeginInvoke((Action)(() => { MessageBox.Show(e.Error.Message); }));
    }

    private void btnSendHttp_Click(object sender, RoutedEventArgs e)
    {
      registrationClient.GetRegisteredSubscribersAsync("HTTP");
    }



    private void btnSendTile_Click(object sender, RoutedEventArgs e)
    {
      registrationClient.GetRegisteredSubscribersAsync("TILE");
    }

    private void btnSendToast_Click(object sender, RoutedEventArgs e)
    {
      if (txtToastMessage.Text.Length > 0)
        registrationClient.GetRegisteredSubscribersAsync("TOAST");
      else
        MessageBox.Show("Cannot send empty Toast notification");
    }

    void registrationClient_GetRegisteredSubscribersCompleted(object sender, RegistrationSVC.GetRegisteredSubscribersCompletedEventArgs e)
    {
      if (null == e.Error)
      {
        if (e.Result.Count > 0)
        {
          switch (e.UserState.ToString())
          {
            case "HTTP":
              Dispatcher.BeginInvoke(() =>
                {
                  //Prepare payload
                  byte[] payload = prepareRAWPayload(cmbLocation.SelectedValue as string,
                                                     sld.Value.ToString("F1"),
                                                     cmbWeather.SelectedValue as string);


                  notificationClient.SendRAWNotificationAsync(e.Result, payload);
                });
              break;
            case "TILE":
              Dispatcher.BeginInvoke(() =>
                {
                  string weatherType = cmbWeather.SelectedValue as string;
                  int temperature = (int)sld.Value;
                  string location = cmbLocation.SelectedValue as string;
                  notificationClient.SendTileNotificationAsync(e.Result, "PushNotificationsToken", "/Images/" + weatherType + ".png", temperature, location);
                });
              break;
            case "TOAST":
              Dispatcher.BeginInvoke(() =>
                {
                  string msg = txtToastMessage.Text;
                  txtToastMessage.Text = "";
                  notificationClient.SendToastNotificationAsync(e.Result, "WEATHER ALERT", msg);
                });
              break;
          }
        }
        else
          MessageBox.Show("No registered subscribers");
      }

      Dispatcher.BeginInvoke(() =>
        {
          MessageBox.Show("Sent notification to " + e.Result.Count + " subscribers");
        });
    }
    #endregion

    #region Private functionality
    private static byte[] prepareRAWPayload(string location, string temperature, string weatherType)
    {
      MemoryStream stream = new MemoryStream();

      XmlWriterSettings settings = new XmlWriterSettings() { Indent = true, Encoding = Encoding.UTF8 };
      XmlWriter writer = XmlWriter.Create(stream, settings);

      writer.WriteStartDocument();
      writer.WriteStartElement("WeatherUpdate");

      writer.WriteStartElement("Location");
      writer.WriteValue(location);
      writer.WriteEndElement();

      writer.WriteStartElement("Temperature");
      writer.WriteValue(temperature);
      writer.WriteEndElement();

      writer.WriteStartElement("WeatherType");
      writer.WriteValue(weatherType);
      writer.WriteEndElement();

      writer.WriteStartElement("LastUpdated");
      writer.WriteValue(DateTime.Now.ToString());
      writer.WriteEndElement();

      writer.WriteEndElement();
      writer.WriteEndDocument();
      writer.Close();

      byte[] payload = stream.ToArray();
      return payload;
    }
    #endregion
  }
}
